﻿using CMS.Excep;
using CMS.Utils;
using Microsoft.AspNetCore.Authorization;
using System.Net;

namespace CMS.Auth
{
    public class MyAuthorizationHandler : AuthorizationHandler<MyAuthorizationRequirement>
    {
        IHttpContextAccessor httpContextAccessor;
        IMyFailureReason reason;
        public MyAuthorizationHandler(IHttpContextAccessor httpContextAccessor, IMyFailureReason reason)
        {
            this.httpContextAccessor = httpContextAccessor;
            this.reason = reason;
        }
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyAuthorizationRequirement requirement)
        {
            var defHttpContext = context.Resource as DefaultHttpContext;
            if (defHttpContext == null || defHttpContext.GetEndpoint() == null)
            {
                requirement.Pass = true;
                context.Succeed(requirement);
                return Task.CompletedTask;
            }
            var clientIp = defHttpContext.Connection.RemoteIpAddress?.ToString();
            var endpoint = defHttpContext.GetEndpoint();
            var ulAtt = endpoint?.Metadata.FirstOrDefault(filter => filter is MyAuthorizeAttribute) as MyAuthorizeAttribute;
            if (ulAtt == null)
            {
                requirement.Pass = true;
                context.Succeed(requirement);
                return Task.CompletedTask;
            }
            try
            {
                var optUser = ServiceLoader.GetService<OptUser>();
                new UserTokenManager().SetupUser(optUser);
                if (optUser.IsAdm)
                {
                    requirement.Pass = true;
                    context.Succeed(requirement);
                    return Task.CompletedTask;
                }
                else if (!ulAtt.AdmRequire)
                {
                    requirement.Pass = true;
                    context.Succeed(requirement);
                    return Task.CompletedTask;
                }
                var msg = $"IP地址[{clientIp}]对API接口{endpoint.DisplayName}的访问的身份级别认证失败:没有适当的验证条件，验证不通过";
                Logger.Err(msg);
                reason.Init(msg, HttpStatusCode.Forbidden);
                context.Fail();
                return Task.CompletedTask;
            }
            catch (MyAuthorizationException ex)
            {
                reason.Init(ex.Message, HttpStatusCode.Unauthorized);
                context.Fail();
                Logger.Err($"IP地址[{clientIp}]对API接口{endpoint.DisplayName}的访问未被认证:{MyUtils.FormatExceptionInfo(ex)}");
                return Task.CompletedTask;
            }
            catch (Exception ex)
            {
                reason.Init(ex.Message, HttpStatusCode.InternalServerError);
                context.Fail();
                Logger.Err($"IP地址[{clientIp}]对API接口{endpoint.DisplayName}的访问未被认证:{MyUtils.FormatExceptionInfo(ex)}");
                return Task.CompletedTask;
            }
        }
    }
}
